package org.lockscreen;

import java.util.ArrayList;
import java.util.List;

public class Matrix {
	public enum Status {
		EMPTY, PASS;
	}

	private Status[][] points;
	private int num;

	public Matrix(int num) {
		if (num < 2)
			throw new IllegalArgumentException("num<2");
		this.num = num;
		points = new Status[num + 1][num + 1];
		for (int i = 1; i <= num; i++) {
			for (int j = 1; j <= num; j++) {
				points[i][j] = Status.EMPTY;
			}
		}
	}

	public void empty(Point p) {
		points[p.getX()][p.getY()] = Status.EMPTY;
	}

	public void setPass(Point p) {
		points[p.getX()][p.getY()] = Status.PASS;
	}

	public Status getStatus(Point p) {
		return points[p.getX()][p.getY()];
	}


	public int getAllTrailSet(int start,int end) {
		if(end<=start)
			throw new IllegalArgumentException("start:"+start+",end:"+end);
		if (start < 2)
			throw new IllegalArgumentException("start<2");
		if (end > num*num)
			throw new IllegalArgumentException("end is too large than matrix");
		int result = 0;
		for (int i = start; i <= end; i++) {
			result += getTrailSet(i);
		}
		return result;
	}

	public int getTrailSet(int step) {
		if (step < 2)
			throw new IllegalArgumentException("step<2");
		if (step > num*num)
			throw new IllegalArgumentException("step is too large than matrix");
		int result = 0;
		for (int x = 1; x <= num; x++) {
			for (int y = 1; y <= num; y++) {
				result += getTrailSetByStart(step - 1, new Point(x, y));
			}
		}
		return result;
	}

	public int getTrailSetByStart(int step, Point start) {
		List<Point> resultList = new ArrayList<Point>();
		int result = 0;
		for (int x = 1; x <= num; x++) {
			for (int y = 1; y <= num; y++) {
				Point p = new Point(x, y);
				if(Status.PASS.equals(getStatus(p))){
					continue;
				}
				if (start.equals(p)) {
					continue;
				}
				List<Point> pointList = Point.getTrail(p, start);
				if (pointList.size() == 0) {
					resultList.add(p);
				} else {
					boolean b = true;
					for (Point currp : pointList) {
						if (getStatus(currp).equals(Status.EMPTY)) {
							b = false;
							break;
						}
					}
					if (b) {
						resultList.add(p);
					}
				}

			}
		}
		if (step == 1) {
			return resultList.size();
		}
		setPass(start);
		for (Point p : resultList) {
			result += getTrailSetByStart(step - 1, p);
			
		}
		empty(start);
		return result;

	}

	public static void main(String[] args) {
		Matrix m = new Matrix(3);
		System.out.println(m.getAllTrailSet(4,9));
	}
}
